package control;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.*;

import model.Simulator;
import model.Values;

/**
 * A class where the Graphical unit interface is built.
 * here the settings are made.
 * 
 * @author Martin Kromkamp and Albert-Jan Boer.
 * @version 2009.01.28
 */

public class GUI extends JFrame implements ActionListener {
	
	private static final int MAX_AGE = 200;
	private static final int MIN_AGE = 1;
	private static final int SPINNER_STEP = 1;
	private static final int MIN_FOOD_VALUE = 1;
	private static final int MAX_FOOD_VALUE = 15;
	private static final double MIN_CREATION_PROB = 0.001;
	private static final double MAX_CREATION_PROB = 0.100;
	private static final double CREATION_SPINNER_STEP = 0.001;
	private static final double MIN_BREEDING_PROB = 0.0;
	private static final double MAX_BREEDING_PROB = 1.0;
	private static final double BREEDING_SPINNER_STEP = 0.1;
	private static final int MIN_FIELD_SIZE = 10;
	private static final int MAX_FIELD_SIZE = 250;
	
	//Buttons
	private JButton startSimButton;
	
	//Labels
	private JLabel  rabbitMaxAgeLabel, rabbitBreedAgeLabel, rabbitBreedProbLabel, rabbitMaxLitterLabel, rabbitCreationProbLabel, rabbitFoodValueLabel,
					foxMaxAgeLabel, foxBreedAgeLabel, foxBreedProbLabel, foxMaxLitterLabel, foxCreationProbLabel, foxFoodValueLabel,
					bearMaxAgeLabel, bearBreedAgeLabel, bearBreedProbLabel, bearMaxLitterLabel, bearCreationProbLabel, bearFoodValueLabel,
					hunterCreationProbLabel,
					fieldWidthLabel, fieldHeightLabel, simStepsLabel, startSimLabel,
					emptyLabel;
	
	//Spinners
	private JSpinner rabbitMaxAgeSpinner, rabbitBreedAgeSpinner, rabbitBreedProbSpinner, rabbitMaxLitterSpinner, rabbitCreationProbSpinner, rabbitFoodValueSpinner,
					 foxMaxAgeSpinner, foxBreedAgeSpinner, foxBreedProbSpinner, foxMaxLitterSpinner, foxCreationProbSpinner, foxFoodValueSpinner,
					 bearMaxAgeSpinner, bearBreedAgeSpinner, bearBreedProbSpinner, bearMaxLitterSpinner, bearCreationProbSpinner, bearFoodValueSpinner,
					 hunterCreationProbSpinner,
					 fieldWidthSpinner, fieldHeightSpinner;
	
	//Checkboxes
	private JCheckBox showHistogramCheckbox;
	
	//Text fields
	private JTextField simStepsField;
	
	//Borders
	private TitledBorder rabbitTitleBorder, foxTitleBorder, bearTitleBorder, hunterTitleBorder, simSettingsBorder;
	
	//Panels
	private JPanel contentPanel, rabbitPanel, foxPanel, bearPanel, hunterPanel, simSettingsPanel;
	
	//Values
	private Values value = new Values();
	
	//Simulator
	Simulator sim;
	
	
	/**
     * Create a GUI.
     */
	public GUI() {
		makeFrame();
	}
	
	/**
     * Make a frame inside the GUI.
     */
	public void makeFrame() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("Foxes and Rabbits - simulator config");		
		contentPanel = (JPanel)getContentPane();
		contentPanel.setLayout( new GridLayout( 2, 2, 25, 25 ) );	
		
		//Add JPanels
		rabbitPanel = new JPanel();
		rabbitPanel.setLayout( new GridLayout( 6,2 ) );
		foxPanel = new JPanel();
		foxPanel.setLayout( new GridLayout( 6,2 ) );
		bearPanel = new JPanel();
		bearPanel.setLayout( new GridLayout( 6,2 ) );
		hunterPanel = new JPanel();
		hunterPanel.setLayout( new GridLayout( 1,2 ) );
		simSettingsPanel = new JPanel();
		simSettingsPanel.setLayout( new GridLayout( 5,2 ) );
		
		//Labels and spinners rabbits
		rabbitTitleBorder = BorderFactory.createTitledBorder("Rabbits!");
		rabbitPanel.setBorder( rabbitTitleBorder );
			//Age
		rabbitMaxAgeLabel = new JLabel( "Max age: " );
		rabbitPanel.add( rabbitMaxAgeLabel );
		rabbitMaxAgeSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_MAX_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		rabbitPanel.add( rabbitMaxAgeSpinner );
			//Breeding age
		rabbitBreedAgeLabel = new JLabel( "Breeding age: " );
		rabbitPanel.add( rabbitBreedAgeLabel );
		rabbitBreedAgeSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_BREEDING_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		rabbitPanel.add( rabbitBreedAgeSpinner );
			//Breeding probabilities
		rabbitBreedProbLabel = new JLabel( "Breeding Probabilitie: " );
		rabbitPanel.add( rabbitBreedProbLabel );
		rabbitBreedProbSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_BREEDING_PROBABILITY, MIN_BREEDING_PROB, MAX_BREEDING_PROB, BREEDING_SPINNER_STEP) );
		rabbitPanel.add( rabbitBreedProbSpinner );
			//Max births
		rabbitMaxLitterLabel = new JLabel( "Max births: " );
		rabbitPanel.add( rabbitMaxLitterLabel );
		rabbitMaxLitterSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_MAX_LITTER_SIZE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		rabbitPanel.add( rabbitMaxLitterSpinner );
			//Creation probabilitie
		rabbitCreationProbLabel = new JLabel( "Creation Probabilitie: " );
		rabbitPanel.add( rabbitCreationProbLabel );
		rabbitCreationProbSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_CREATION_PROBABILITY, MIN_CREATION_PROB, MAX_CREATION_PROB, CREATION_SPINNER_STEP) );
		rabbitPanel.add( rabbitCreationProbSpinner );
			//Food value
		rabbitFoodValueLabel = new JLabel( "Food value: " );
		rabbitPanel.add( rabbitFoodValueLabel );
		rabbitFoodValueSpinner = new JSpinner( new SpinnerNumberModel(value.RABBIT_FOOD_VALUE, MIN_FOOD_VALUE, MAX_FOOD_VALUE, SPINNER_STEP) );
		rabbitPanel.add( rabbitFoodValueSpinner );
		
		//Labels and spinners Foxes
		foxTitleBorder = BorderFactory.createTitledBorder("Foxes!");
		foxPanel.setBorder( foxTitleBorder );
			//Age
		foxMaxAgeLabel = new JLabel( "Max age: " );
		foxPanel.add( foxMaxAgeLabel );
		foxMaxAgeSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_MAX_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		foxPanel.add( foxMaxAgeSpinner );
			//Breeding age
		foxBreedAgeLabel = new JLabel( "Breeding age: " );
		foxPanel.add( foxBreedAgeLabel );
		foxBreedAgeSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_BREEDING_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		foxPanel.add( foxBreedAgeSpinner );
			//Breeding probabilities
		foxBreedProbLabel = new JLabel( "Breeding Probabilitie: " );
		foxPanel.add( foxBreedProbLabel );
		foxBreedProbSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_BREEDING_PROBABILITY, MIN_BREEDING_PROB, MAX_BREEDING_PROB, BREEDING_SPINNER_STEP) );
		foxPanel.add( foxBreedProbSpinner );
			//Max births
		foxMaxLitterLabel = new JLabel( "Max births: " );
		foxPanel.add( foxMaxLitterLabel );
		foxMaxLitterSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_MAX_LITTER_SIZE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		foxPanel.add( foxMaxLitterSpinner );
			//Creation probabilitie
		foxCreationProbLabel = new JLabel( "Creation Probabilitie: " );
		foxPanel.add( foxCreationProbLabel );
		foxCreationProbSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_CREATION_PROBABILITY, MIN_CREATION_PROB, MAX_CREATION_PROB, CREATION_SPINNER_STEP) );
		foxPanel.add( foxCreationProbSpinner );
			//Food value
		foxFoodValueLabel = new JLabel( "Food value: " );
		foxPanel.add( foxFoodValueLabel );
		foxFoodValueSpinner = new JSpinner( new SpinnerNumberModel(value.FOX_FOOD_VALUE, MIN_FOOD_VALUE, MAX_FOOD_VALUE, SPINNER_STEP) );
		foxPanel.add( foxFoodValueSpinner );
		
		//Labels and spinners Bears
		bearTitleBorder = BorderFactory.createTitledBorder("Bears!");
		bearPanel.setBorder( bearTitleBorder );
			//Age
		bearMaxAgeLabel = new JLabel( "Max age: " );
		bearPanel.add( bearMaxAgeLabel );
		bearMaxAgeSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_MAX_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		bearPanel.add( bearMaxAgeSpinner );
			//Breeding age
		bearBreedAgeLabel = new JLabel( "Breeding age: " );
		bearPanel.add( bearBreedAgeLabel );
		bearBreedAgeSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_BREEDING_AGE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		bearPanel.add( bearBreedAgeSpinner );
			//Breeding probabilities
		bearBreedProbLabel = new JLabel( "Breeding Probabilitie: " );
		bearPanel.add( bearBreedProbLabel );
		bearBreedProbSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_BREEDING_PROBABILITY, MIN_BREEDING_PROB, MAX_BREEDING_PROB, BREEDING_SPINNER_STEP) );
		bearPanel.add( bearBreedProbSpinner );
			//Max births
		bearMaxLitterLabel = new JLabel( "Max births: " );
		bearPanel.add( bearMaxLitterLabel );
		bearMaxLitterSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_MAX_LITTER_SIZE, MIN_AGE, MAX_AGE, SPINNER_STEP) );
		bearPanel.add( bearMaxLitterSpinner );
			//Creation probabilitie
		bearCreationProbLabel = new JLabel( "Creation Probabilitie: " );
		bearPanel.add( bearCreationProbLabel );
		bearCreationProbSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_CREATION_PROBABILITY, MIN_CREATION_PROB, MAX_CREATION_PROB, CREATION_SPINNER_STEP) );
		bearPanel.add( bearCreationProbSpinner );
			//Food value
		bearFoodValueLabel = new JLabel( "Food value: " );
		bearPanel.add( bearFoodValueLabel );
		bearFoodValueSpinner = new JSpinner( new SpinnerNumberModel(value.BEAR_FOOD_VALUE, MIN_FOOD_VALUE, MAX_FOOD_VALUE, SPINNER_STEP) );
		bearPanel.add( bearFoodValueSpinner );
		
		//Labels and spinners Hunters
		hunterTitleBorder = BorderFactory.createTitledBorder("Hunters!");
		hunterPanel.setBorder( hunterTitleBorder );
			//Creation probabilitie
		hunterCreationProbLabel = new JLabel( "Creation Probabilitie: " );
		hunterPanel.add( hunterCreationProbLabel );
		hunterCreationProbSpinner = new JSpinner( new SpinnerNumberModel(value.HUNTER_CREATION_PROBABILITY, MIN_CREATION_PROB, MAX_CREATION_PROB, CREATION_SPINNER_STEP) );
		hunterPanel.add( hunterCreationProbSpinner );
		
		
		//Simulation settings
		simSettingsBorder = BorderFactory.createTitledBorder("Simulation settings");
		simSettingsPanel.setBorder( simSettingsBorder );
			//Field settings
		fieldWidthLabel = new JLabel( "Field width: " );
		simSettingsPanel.add( fieldWidthLabel );
		fieldWidthSpinner = new JSpinner( new SpinnerNumberModel(MAX_FIELD_SIZE/2, MIN_FIELD_SIZE, MAX_FIELD_SIZE, SPINNER_STEP) );
		simSettingsPanel.add( fieldWidthSpinner );
		fieldHeightLabel = new JLabel( "Field height: " );
		simSettingsPanel.add( fieldHeightLabel );
		fieldHeightSpinner = new JSpinner( new SpinnerNumberModel(MAX_FIELD_SIZE/2, MIN_FIELD_SIZE, MAX_FIELD_SIZE, SPINNER_STEP) );
		simSettingsPanel.add( fieldHeightSpinner );
		simStepsLabel = new JLabel( "Simulation steps: " );
		simSettingsPanel.add( simStepsLabel );
		simStepsField = new JTextField();
		simSettingsPanel.add( simStepsField );
			//View settings
		showHistogramCheckbox = new JCheckBox( "Show histogram" );
		showHistogramCheckbox.setSelected( true );
		simSettingsPanel.add( showHistogramCheckbox );
		emptyLabel = new JLabel();
		simSettingsPanel.add( emptyLabel );
			//Run Button
		startSimLabel = new JLabel( "Start simulation: " );
		simSettingsPanel.add( startSimLabel );
		startSimButton = new JButton( "Run!!" );
		startSimButton.addActionListener( this );
		simSettingsPanel.add( startSimButton );
		
		
		//Add Panels to ContentPanel
		contentPanel.add( rabbitPanel );
		contentPanel.add( foxPanel );
		contentPanel.add( bearPanel );
		contentPanel.add( hunterPanel );
		contentPanel.add( simSettingsPanel );
		
		//Pack the frame and make it visible
		pack();
		setVisible(true);
	}
	
	/**
     * Checks for an action from the button.
     * @param a JButton.
     */
	 public void actionPerformed(ActionEvent e) {
			if(e.getSource() == startSimButton){
				
				//rabbits settings
				value.RABBIT_MAX_AGE = Integer.parseInt( "" + rabbitMaxAgeSpinner.getValue() );
				value.RABBIT_BREEDING_AGE = Integer.parseInt( "" + rabbitBreedAgeSpinner.getValue() );
				value.RABBIT_BREEDING_PROBABILITY = Double.parseDouble( "" + rabbitBreedProbSpinner.getValue() );
				value.RABBIT_MAX_LITTER_SIZE = Integer.parseInt( "" + rabbitMaxLitterSpinner.getValue() );
				value.RABBIT_CREATION_PROBABILITY = Double.parseDouble( "" + rabbitCreationProbSpinner.getValue() );
				value.RABBIT_FOOD_VALUE = Integer.parseInt( "" + rabbitFoodValueSpinner.getValue() );
				
				//foxes settings
				value.FOX_MAX_AGE = Integer.parseInt( "" + foxMaxAgeSpinner.getValue() );
				value.FOX_BREEDING_AGE = Integer.parseInt( "" + foxBreedAgeSpinner.getValue() );
				value.FOX_BREEDING_PROBABILITY = Double.parseDouble( "" + foxBreedProbSpinner.getValue() );
				value.FOX_MAX_LITTER_SIZE = Integer.parseInt( "" + foxMaxLitterSpinner.getValue() );
				value.FOX_CREATION_PROBABILITY = Double.parseDouble( "" + foxCreationProbSpinner.getValue() );
				value.FOX_FOOD_VALUE = Integer.parseInt( "" + foxFoodValueSpinner.getValue() );
				
				//bears settings
				value.BEAR_MAX_AGE = Integer.parseInt( "" + bearMaxAgeSpinner.getValue() );
				value.BEAR_BREEDING_AGE = Integer.parseInt( "" + bearBreedAgeSpinner.getValue() );
				value.BEAR_BREEDING_PROBABILITY = Double.parseDouble( "" + bearBreedProbSpinner.getValue() );
				value.BEAR_MAX_LITTER_SIZE = Integer.parseInt( "" + bearMaxLitterSpinner.getValue() );
				value.BEAR_CREATION_PROBABILITY = Double.parseDouble( "" + bearCreationProbSpinner.getValue() );
				value.BEAR_FOOD_VALUE = Integer.parseInt( "" + bearFoodValueSpinner.getValue() );
				
				//hunters settings
				value.HUNTER_CREATION_PROBABILITY = Double.parseDouble( "" + hunterCreationProbSpinner.getValue() );
				
				//Field settings
				value.DEFAULT_WIDTH = Integer.parseInt( "" + fieldWidthSpinner.getValue() );
				value.DEFAULT_DEPTH = Integer.parseInt( "" + fieldHeightSpinner.getValue() );
				
				//View settings
				value.showHistogram = showHistogramCheckbox.isSelected();
				
				//Simulation settings
				if( simStepsField.getText().equals( "" ) ) {
					value.NUMSTEPS = 100;
				} else {
					value.NUMSTEPS = Integer.parseInt( simStepsField.getText() );
				}

				
				sim = new Simulator(value.DEFAULT_WIDTH, value.DEFAULT_DEPTH, value);
				new Thread(sim).start();
			}

	 }
				
	 /**
	 * A main function.
	 */
	public static void main(String[] args)
    {
    	new GUI();
    	
    }

	
}
